home *** CD-ROM | disk | FTP | other *** search
- /*
- ***********************************************************************
- *
- *
- * Simple Window Class
- *
- *
- ***********************************************************************
- */
-
- #include "image.h"
- #include "window.h"
- #include <PictUtil.h>
-
- /*
- *----------------------------------------------------------------------
- * Service functions
- */
-
- // Getting a bounding rectangle of an image
- ScreenRect::ScreenRect(const IMAGE& image)
- {
- top = 0;
- bottom = top + image.q_nrows();
- left = 0;
- right = left + image.q_ncols();
- }
-
- // Create a rectangle of given height/width
- // positioned at the origin
- ScreenRect::ScreenRect(const rowcol& heightwidth)
- {
- left = top = 0;
- bottom = heightwidth.row();
- right = heightwidth.col();
- }
-
- // Create a rectangle of given height/width
- // positioned at a given point
- ScreenRect::ScreenRect(const rowcol& origin, const rowcol& heightwidth)
- {
- top = origin.row();
- left = origin.col();
- bottom = top+heightwidth.row();
- right = left+heightwidth.col();
- }
-
-
- // Shifting a rectangle by the same amount
- // in X and Y
- ScreenRect& ScreenRect::operator += (const int offset)
- {
- top += offset; bottom += offset; left += offset; right += offset;
- return *this;
- }
-
-
- // Print what rectangle is this
- void ScreenRect::print(const char * title) const
- {
- message("Rectangle %s (%d,%d) - (%d,%d)",title,top,left,bottom,right);
- }
-
-
-
- // Used to "implicitly" convert from C to Pascal
- // string
- Pstr::Pstr(const char * c_str)
- {
- strncpy((char *)pas_string,c_str,sizeof(*this)-2);
- CtoPstr((char *)pas_string);
- }
-
- /*
- *----------------------------------------------------------------------
- * A generic simple window that can be dragged around the screen
- * and closed by clicking a "go-away" button
- * No other events are handled, redefine the event handler if necessary.
- */
-
-
- // Create a color window of the specified size and title
- // Note, the upper left corner of 'rect' must
- // NOT be (0,0)!
- ScreenWindow::ScreenWindow(ScreenRect rect, const char * title)
- {
- const int window_offset = 100; // Cannot be 0 or small!
- this_window = NewCWindow(nil,rect += window_offset,(Pstr)title,
- TRUE,noGrowDocProc,
- (WindowPtr)(-1),TRUE,(long)this);
- assert( this_window != 0 );
- SetPort(this_window);
- SelectWindow(this_window);
- }
-
- // Create a color window from a resource template
- ScreenWindow::ScreenWindow(const short resource_id)
- {
- this_window = GetNewCWindow(resource_id,nil,(WindowPtr)(-1));
- SetWRefCon(this_window,(long)this);
- assert( this_window != 0 );
- SetPort(this_window);
- SelectWindow(this_window);
- }
-
-
-
- // Close the window and clean up the rubble
- ScreenWindow::~ScreenWindow(void)
- {
- assert( this_window != 0 );
- DisposeWindow(this_window);
- this_window = 0;
- }
-
-
- // Event handling loop. Returns only when the
- // window is to be destroyed
- void ScreenWindow::handle(void)
- {
- const long event_timeout = 20;
- EventRecord theEvent;
-
- for(;;)
- {
- if( !WaitNextEvent(everyEvent, &theEvent,event_timeout,nil) )
- if( handle_null_event(theEvent.when) )
- continue;
- else
- return;
- switch (theEvent.what)
- {
- case mouseDown:
- if( !handle_mouse_down(theEvent) )
- return; // Window is to be closed (go-away buttin clicked)
- break;
-
- case updateEvt:
- if( this_window == (WindowPtr)theEvent.message )
- update();
- break;
-
- case keyDown:
- case autoKey:
- if( !handle_key_down(theEvent) )
- return; // a "quit" key must've been pressed
- break;
-
- case activateEvt:
- if( this_window == (WindowPtr)theEvent.message )
- activate(theEvent.modifiers & 0x01);
- break;
- }
- }
-
- }
-
- // Handle "mouse-down" events
- // Returns FALSE if the user clicked within the
- // go-away region of our window. Otherwise,
- // returns TRUE
- // Handles dragging if necessary and system clicks
- Boolean ScreenWindow::handle_mouse_down(const EventRecord& the_event)
- {
- WindowPtr wp;
- short windowPart = FindWindow (the_event.where, &wp);
-
- switch (windowPart)
- {
- case inSysWindow:
- SystemClick(&the_event, wp);
- break;
-
- case inMenuBar:
- break;
-
- case inContent:
- break;
-
- case inDrag:
- if (wp == this_window )
- drag(the_event.where);
- break;
-
- case inGoAway:
- return FALSE;
- }
- return TRUE;
- }
-
- // Handles key_down & auto_key events. Return FALSE
- // if the window is to be closed down
- Boolean ScreenWindow::handle_key_down(const EventRecord& the_event)
- {
- return FALSE; // Each key kills the application, sorry
- }
-
-
- // Handles null events, when nothing happens for some
- // time. Return FALSE when it's time to die
- Boolean ScreenWindow::handle_null_event(const long event_time)
- {
- return TRUE; // Keep going
- }
-
- // Private window parts
- // Handle an update event - redraw the window
- // A virtual function draw() is called to do
- // the actual redrawing
- void ScreenWindow::update(void)
- {
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(this_window);
- BeginUpdate(this_window);
- draw();
- EndUpdate(this_window);
- SetPort(savePort);
- }
-
- // Make the entire window being redrawn
- void ScreenWindow::refresh(void)
- {
- // EraseRect(&this_window->portRect);
- InvalRect(&this_window->portRect);
- }
-
- // Handle an activate or deactivate event
- void ScreenWindow::activate (const Boolean go_active)
- {
- if (go_active)
- SetPort(this_window);
- }
-
-
- /*
- *----------------------------------------------------------------------
- * A simple window with an offscreen window buffer
- */
-
- // Allocate the buffer for the offscreen
- // drawing and load CLUT (if clut_id != 0)
- OffScreenWindow::OffScreenWindow
- (ScreenRect rect, const char * title, const short clut_id)
- : ScreenWindow(rect,title), graf_world(nil)
- {
- CTabHandle clut_handle = nil;
- if( clut_id != 0 )
- { // try to get a user CLUT with that resource id
- clut_handle = GetCTable(clut_id);
- assert( clut_handle != 0 );
- SetWinColor(our_window(),(WinCTab**)clut_handle);
- }
- do_well( NewGWorld(&graf_world,8,rect,clut_handle,nil,0) );
- assert( graf_world != (void *)0 );
-
- // if( clut_handle != nil )
- // DisposCTable(clut_handle); // CLUT has been copied, and can be disposed of now
- // But careful! CLUT is associated with the window
- // by SetWinColor(), so we don't dispose of it
-
- // Get hold of the offscreen pixmap
- pixmap = GetGWorldPixMap(graf_world); // and make sure it looks like
- assert( pixmap != nil && *pixmap != nil ); // we can use it
-
- assert( (**pixmap).cmpCount == 1 ); // We have a color table index
- assert( !PixMap32Bit(pixmap) );
-
- _height = abs((**pixmap).bounds.top - (**pixmap).bounds.bottom);
- _width = abs((**pixmap).bounds.right - (**pixmap).bounds.left);
- _bytes_per_row = (**pixmap).rowBytes & 0x7fff;
-
- assert( _height > 0 && _height < 10000 ); // Just to play safe
- assert( _width > 0 && _width <= _bytes_per_row );
-
- activate_palette(); // Activate palette for the window
- }
-
- // Dispose of the offscreen buffer
- OffScreenWindow::~OffScreenWindow(void)
- {
- assert( graf_world != nil );
- DisposeGWorld(graf_world);
- graf_world = nil;
- PaletteHandle window_palette = GetPalette(our_window());
- if( window_palette != nil ) // dispose of our palette if was allocated
- {
- SetPalette(our_window(),nil,FALSE);
- DisposePalette(window_palette);
- }
- pixmap = nil;
- _height = _width = _bytes_per_row = 0;
- }
-
- // Make sure that the colors of our off-screen
- // buffer would be displayed properly (or close enough)
- // on screen
- void OffScreenWindow::activate_palette(void)
- {
- CTabHandle window_ctab = (**pixmap).pmTable;
- assert( window_ctab != nil && *window_ctab != nil );
-
- PaletteHandle palette = NewPalette((**window_ctab).ctSize,window_ctab,pmTolerant+pmExplicit,0);
- assert( palette != nil );
- SetPalette(our_window(),palette,TRUE);
- do_well( QDError() );
- ActivatePalette(our_window());
- do_well( QDError() );
- }
-
-
- // Get a bounding rectangle for the window
- ScreenRect OffScreenWindow::q_bounds(void) const
- {
- return (**pixmap).bounds;
- }
-
-
- // Actual drawing - moving the picture from the
- // offscreen grafworld to the onscreen one
- void OffScreenWindow::draw(void)
- {
- assert( LockPixels(pixmap) );
- Rect& pixmap_rect = (**pixmap).bounds;
- CopyBits((const BitMap *)*pixmap, &thePort->portBits, &pixmap_rect,
- &our_window()->portRect, /*ditherCopy*/ srcCopy, nil);
- UnlockPixels(pixmap);
- }
-